package cn.turboinfo.fuyang.api.domain.common.component.credit

import cn.turboinfo.fuyang.api.domain.common.service.credit.CreditRatingService
import cn.turboinfo.fuyang.api.domain.common.service.order.ServiceOrderService
import cn.turboinfo.fuyang.api.domain.common.service.product.ProductService
import cn.turboinfo.fuyang.api.domain.common.service.shop.HousekeepingShopService
import cn.turboinfo.fuyang.api.domain.common.service.staff.HousekeepingStaffService
import cn.turboinfo.fuyang.api.domain.common.service.user.SysUserService
import cn.turboinfo.fuyang.api.domain.util.PhoneUtils
import cn.turboinfo.fuyang.api.entity.common.enumeration.common.EntityObjectType
import cn.turboinfo.fuyang.api.entity.common.enumeration.credit.CreditRatingStatus
import cn.turboinfo.fuyang.api.entity.common.enumeration.order.ServiceOrderCreditRatingStatus
import cn.turboinfo.fuyang.api.entity.common.pojo.credit.ServiceOrderCreditRating
import cn.turboinfo.fuyang.api.entity.common.pojo.order.QServiceOrder
import cn.turboinfo.fuyang.api.entity.common.pojo.order.ServiceOrder
import net.sunshow.toolkit.core.qbean.api.request.QPage
import net.sunshow.toolkit.core.qbean.api.request.QRequest
import net.sunshow.toolkit.core.qbean.api.request.QSort
import net.sunshow.toolkit.core.qbean.api.response.QResponse
import org.springframework.stereotype.Component
import java.util.stream.Collectors

@Component
class CreditRatingAssembleHelper(
    private val serviceOrderService: ServiceOrderService,
    private val creditRatingService: CreditRatingService,
    private val sysUserService: SysUserService,
    private val housekeepingShopService: HousekeepingShopService,
    private val housekeepingStaffService: HousekeepingStaffService,
    private val productService: ProductService,
) {

    companion object {
        const val ASSEMBLE_NONE = 0

        const val ASSEMBLE_USER = 1 shl 0
        const val ASSEMBLE_PRODUCT = 1 shl 1
        const val ASSEMBLE_STAFF = 1 shl 2
        const val ASSEMBLE_SHOP = 1 shl 3

        const val ASSEMBLE_ALL = ASSEMBLE_USER + ASSEMBLE_PRODUCT + ASSEMBLE_STAFF + ASSEMBLE_SHOP
    }

    fun findLatestPageable(
        objectType: EntityObjectType,
        objectId: Long,
        pageIndex: Int = 0,
        pageSize: Int = 10,
    ): QResponse<ServiceOrderCreditRating> {
        return findLatestPageable(objectType, objectId, pageIndex, pageSize, ASSEMBLE_NONE)
    }

    /**
     * 最终评价都是基于服务订单的, 所以抽象为根据某个对象ID获取服务订单列表, 最后转换成订单评价列表
     */
    fun findLatestPageable(
        objectType: EntityObjectType,
        objectId: Long,
        pageIndex: Int = 0,
        pageSize: Int = 10,
        assembleFlag: Int,
    ): QResponse<ServiceOrderCreditRating> {
        // 查询最近评价完成的订单
        val requestPage = QPage.newInstance()
            .paging(pageIndex, pageSize)
            .addOrder(QServiceOrder.createdTime, QSort.Order.DESC)

        val request = QRequest.newInstance()
            .filterEqual(QServiceOrder.creditRatingStatus, ServiceOrderCreditRatingStatus.SUBMITTED)

        // 根据不同的对象类型, 过滤不同的对象ID
        when (objectType) {
            EntityObjectType.PRODUCT -> {
                request.filterEqual(QServiceOrder.productId, objectId)
            }

            EntityObjectType.COMPANY -> {
                request.filterEqual(QServiceOrder.companyId, objectId)
            }

            EntityObjectType.SHOP -> {
                request.filterEqual(QServiceOrder.shopId, objectId)
            }

            EntityObjectType.STAFF -> {
                request.filterEqual(QServiceOrder.staffId, objectId)
            }

            else -> {
                throw IllegalArgumentException("不支持的对象类型: $objectType")
            }
        }

        val orderCollection = serviceOrderService.findAll(request, requestPage)

        // 评价编码集合
        val orderIdSet = orderCollection.pagedData.stream()
            .map { obj: ServiceOrder -> obj.id }
            .collect(Collectors.toSet())

        val orderIdRatingListMap =
            creditRatingService.findByObjectIdCollection(EntityObjectType.SERVICE_ORDER, orderIdSet)
                // 过滤审核通过的评价
                .filter { creditRating -> creditRating.status == CreditRatingStatus.REVIEWED }
                .groupBy {
                    it.objectId
                }

        // 转换成目标对象
        val result = orderCollection
            .map {
                val serviceOrderCreditRating = ServiceOrderCreditRating()

                serviceOrderCreditRating.serviceOrderId = it.id
                serviceOrderCreditRating.serviceOrder = it
                serviceOrderCreditRating.ratingList = orderIdRatingListMap[it.id]

                serviceOrderCreditRating
            }

        // 拼装用户信息
        if (assembleFlag and ASSEMBLE_USER != 0) {
            // 用户信息集合
            val userIdSet = orderCollection.pagedData
                .map {
                    it.userId
                }
                .toSet()
            val userIdMap = sysUserService.findByIdCollection(userIdSet)
                .associateBy {
                    it.id
                }

            result.pagedData
                .onEach {
                    // 手机号打码作为显示名
                    it.displayName = PhoneUtils.maskPhoneNum(userIdMap[it.serviceOrder.userId]!!.mobile)

                    // TODO 获取用户头像
                }
        }

        if (assembleFlag and ASSEMBLE_PRODUCT != 0) {
            // 产品信息集合
            val productIdSet = orderCollection.pagedData
                .map {
                    it.productId
                }
                .toSet()
            val productIdMap = productService.findByIdCollection(productIdSet)
                .associateBy {
                    it.id
                }

            result.pagedData
                .onEach {
                    it.product = productIdMap[it.serviceOrder.productId]
                }
        }

        if (assembleFlag and ASSEMBLE_STAFF != 0) {
            // 家政员信息集合
            val staffIdSet = orderCollection.pagedData
                .map {
                    it.staffId
                }
                .toSet()
            val staffIdMap = housekeepingStaffService.findByIdCollection(staffIdSet)
                .associateBy {
                    it.id
                }

            result.pagedData
                .onEach {
                    it.staff = staffIdMap[it.serviceOrder.staffId]
                }
        }

        if (assembleFlag and ASSEMBLE_SHOP != 0) {
            // 店铺信息集合
            val shopIdSet = orderCollection.pagedData
                .map {
                    it.shopId
                }
                .toSet()
            val shopIdMap = housekeepingShopService.findByIdCollection(shopIdSet)
                .associateBy {
                    it.id
                }

            result.pagedData
                .onEach {
                    it.shop = shopIdMap[it.serviceOrder.shopId]
                }
        }

        return result
    }

}
